#include "Base64.h"

namespace red {
namespace protocolo {
namespace mensajes {

Base64::Base64() {
}

Base64::~Base64() {
}

char Base64::encode(unsigned char p_uc) {

	char t_c;

	if (p_uc < 26) {
		t_c = 'A' + p_uc;
	} else if (p_uc < 52) {
		t_c = 'a' + (p_uc - 26);
	} else if (p_uc < 62) {
		t_c = '0' + (p_uc - 52);
	} else if (p_uc == 62) {
		t_c = '+';
	} else {
       t_c = '/';
	}

	return t_c;
};

unsigned char Base64::decode(char p_c) {

	char t_uc;

	if (p_c >= 'A' && p_c <= 'Z') {
		t_uc = p_c - 'A';
	} else if (p_c >= 'a' && p_c <= 'z') {
		t_uc = p_c - 'a' + 26;
	} else if (p_c >= '0' && p_c <= '9') {
		t_uc = p_c - '0' + 52;
	} else if (p_c == '+') {
		t_uc = 62;
	} else {
		t_uc = 63;
	}

	return t_uc;
};

bool Base64::isBase64(char p_c) {

	bool t_b = true;

	if (p_c >= 'A' && p_c <= 'Z') {
	} else if (p_c >= 'a' && p_c <= 'z') {
	} else if (p_c >= '0' && p_c <= '9') {
	} else if (p_c == '+') {
	} else if (p_c == '/') {
	} else if (p_c == '=') {
	} else {
		t_b = false;
	}

	return t_b;
};

string Base64::encode(const string &vby) {

	string retval;
	unsigned char by1 = 0, by2 = 0, by3 = 0;
	unsigned char by4 = 0, by5 = 0, by6 = 0, by7 = 0;

	if (vby.size() == 0) {
		return retval;
	};

	for (int i = 0; i < vby.size(); i += 3) {

		by1 = vby[i];

		if (i + 1 < vby.size()) {
			by2 = vby[i + 1];
		};

		if (i + 2 < vby.size()) {
			by3 = vby[i + 2];
		}

		by4 = by1 >> 2;
		by5 = ((by1 & 0x3) << 4) | (by2 >> 4);
		by6 = ((by2 & 0xf) << 2) |(by3 >> 6);
		by7 = by3 & 0x3f;

		retval += encode(by4);
		retval += encode(by5);

		if (i + 1 < vby.size()) {
			retval += encode(by6);
		} else {
			retval += "=";
		}

		if (i + 2 < vby.size()) {
			retval += encode(by7);
		} else {
			retval += "=";
		}

		if (i % (76 / 4 * 3) == 0) {
			retval += "\r\n";
		}
	}

	return retval;
};

string Base64::decode(const string &p_sOrigen) {

	string str;
	string retval;
	char c1 = 'A', c2 = 'A', c3 = 'A', c4 = 'A';
	unsigned char by1 = 0, by2 = 0, by3 = 0, by4 = 0;

	for (int j = 0; j < p_sOrigen.length(); j++) {

		if (isBase64(p_sOrigen[j])) {
			str += p_sOrigen[j];
		}
	}

	if (str.length() == 0) {
		return retval;
	}

	for (int i = 0; i < str.length(); i += 4) {

		c1 = str[i];

		if (i + 1 < str.length()) {
			c2 = str[i + 1];
		}

		if (i + 2 < str.length()) {
			c3 = str[i + 2];
		}

		if (i + 3 < str.length()) {
			c4 = str[i + 3];
		}
			
		by1 = decode(c1);
		by2 = decode(c2);
		by3 = decode(c3);
		by4 = decode(c4);

		retval.append(1, static_cast<char>((by1 << 2) | (by2 >> 4)));

		if (c3 != '=') {
			retval.append(1, static_cast<char>(((by2 & 0xf) << 4) | (by3 >> 2)));
		}

		if (c4 != '=') {
			retval.append(1, static_cast<char>(((by3 & 0x3) << 6) | by4));
		}
	}

	return retval;
};

}
}
}
